package com.gitee.wsl.compose.chart.polar.axis

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.gitee.wsl.unit.angle.AngleUnit
import com.gitee.wsl.unit.angle.PolarAngleDirection
import com.gitee.wsl.unit.angle.PolarAngleZero
import com.gitee.wsl.unit.angle.rad
import kotlin.math.PI

/**
 * An [AngularAxisModel] that uses category values evenly spaced around the perimeter of the Polar plot. Values
 * plotted on this axis can only exactly match one of the category values.
 *
 * @param categories The category values represented by this axis.
 */
 data class CategoryAngularAxisModel<T>(
    private val categories: List<T>,
    override val polarAngleDirection: PolarAngleDirection = PolarAngleDirection.CLOCKWISE,
    override val polarAngleZero: PolarAngleZero = PolarAngleZero.TWELVE_OCLOCK
) : AngularAxisModel<T> {
    override fun getTickValues(): List<T> = categories

    override fun computeOffset(point: T): AngleUnit {
        val index = categories.indexOf(point)
        require(index != -1) { "The provided category '$point' is not a valid value for this axis." }
        return ((index * 2.0 * PI) / categories.size).rad
    }
}

/**
 * Creates and remembers a [CategoryAngularAxisModel].
 */
@Composable
 fun <T> rememberCategoryAngularAxisModel(
    categories: List<T>,
    polarAngleDirection: PolarAngleDirection = PolarAngleDirection.CLOCKWISE,
    polarAngleZero: PolarAngleZero = PolarAngleZero.TWELVE_OCLOCK
): CategoryAngularAxisModel<T> =
    remember(categories, polarAngleDirection, polarAngleZero) {
        CategoryAngularAxisModel(categories, polarAngleDirection, polarAngleZero)
    }

@Composable
fun <T> AngularAxisModel.Companion.Category(categories: List<T>,
                                        polarAngleDirection: PolarAngleDirection = PolarAngleDirection.CLOCKWISE,
                                        polarAngleZero: PolarAngleZero = PolarAngleZero.TWELVE_OCLOCK
) = rememberCategoryAngularAxisModel(categories, polarAngleDirection, polarAngleZero)